package com.wooming.myserver.security;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wooming.myserver.constant.Security;
import com.wooming.myserver.dto.JwtDTO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT 安全工具类
 *
 * @author Wooming 2025/05/20
 */
@Component
public class JWT {
    // 依赖注入算法与密钥(失效,原因未知)
    @Value("${server.encryption.algorithm}")
    private static final String ALGORITHM = Security.ALGORITHM.getValue();
    @Value("${server.encryption.key}")
    private static final String secretKey = Security.KEY.getValue();
    // 形成密钥
    private static final SecretKeySpec key = new SecretKeySpec(secretKey.getBytes(), ALGORITHM);

    // 生成 JWT
    public static String generate(JwtDTO data) throws Exception {
        // Header
        Map<String, String> header = new HashMap<>();
        header.put("alg", "SHA256");
        header.put("typ", "JWT");

        // Payload
        Map<String, Object> payload = new HashMap<>();
        payload.put("sub",  data.getSub());
        payload.put("username",  data.getUsername());
        payload.put("stage", data.getStage());
        payload.put("role", data.getRole());

        // 转JSON并编码
        String headerStr = encode(header);
        String payloadStr = encode(payload);

        // 签名
        String signature = sign(headerStr + "." + payloadStr);

        // 返回JWT
        return headerStr + "." + payloadStr + "." + signature;
    }

    // 验证 JWT
    public static boolean verifyJWT(String jwt) throws Exception {
        // 解码 JWT
        String[] parts = jwt.split("\\.");
        if (parts.length != 3) {
            return false;
        }
        String encodedHeader = parts[0];
        String encodedPayload = parts[1];
        String signature = parts[2];

        // 验证签名
        String signingInput = encodedHeader + "." + encodedPayload;
        String expectedSignature = sign(signingInput);

        // 返回验证结果
        return expectedSignature.equals(signature);
    }

    // 解码 JWT
    public static JwtDTO decode(String jwt) throws Exception {
        // 确保JWT有效
        if (!verifyJWT(jwt)) {
            return null;
        }
        String[] parts = jwt.split("\\.");
        if (parts.length != 3) {
            return null;
        }
        //  解码 Payload
        String encodedPayload = parts[1];
        String payloadStr = new String(Base64.getUrlDecoder().decode(encodedPayload));
        return new ObjectMapper().readValue(payloadStr, JwtDTO.class);
    }

    // HMAC 签名
    private static String sign(String data) throws Exception {
        // 创建 MAC
        Mac mac = Mac.getInstance(ALGORITHM);
        mac.init(key);

        // 计算签名
        byte[] rawHmac = mac.doFinal(data.getBytes());

        // 返回签名
        return Base64.getUrlEncoder().withoutPadding().encodeToString(rawHmac);
    }

    // Base64 URL 编码
    private static String encode(Object obj) throws JsonProcessingException {
        //  转JSON
        String json = new ObjectMapper().writeValueAsString(obj);

        // 编码
        return Base64.getUrlEncoder().withoutPadding().encodeToString(json.getBytes());
    }
}
